package cn.xianshu.service.impl;

import cn.xianshu.constants.BaseConstants;
import cn.xianshu.constants.RedisConstants;
import cn.xianshu.domain.Login;
import cn.xianshu.domain.VipBase;
import cn.xianshu.domain.VipUser;
import cn.xianshu.dto.UserRegisterDto;
import cn.xianshu.mapper.VipBaseMapper;
import cn.xianshu.mapper.VipUserMapper;
import cn.xianshu.feign.client.LoginFeignClient;
import cn.xianshu.service.IVipUserService;
import cn.xianshu.to.SendVerifyCodeTo;
import cn.xianshu.util.AjaxResult;
import cn.xianshu.util.AssertUtil;
import cn.xianshu.util.BitStatesUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.sun.org.apache.bcel.internal.generic.NEW;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;


/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author Uncle Xian
 * @since 2021-12-02
 */
@Service
public class VipUserServiceImpl extends ServiceImpl<VipUserMapper, VipUser> implements IVipUserService {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    private LoginFeignClient loginFeignClient;

    @Autowired
    private VipBaseMapper vipBaseMapper;


    /**
     * 提交注册
     * 1.判断参数
     * 2.判断手机是否已经被注册
     * 3.判断手机验证码
     * 3.1.获取Redis中的手机验证码
     * 3.2.和传入的手机验证码比较
     * 4.保存Login
     * 5.保存User
     * 6.保存Base
     * 7.删除手机验证码
     * @param dto
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void register(UserRegisterDto dto) {
        // 1.判断参数
        String mobile = dto.getMobile();
        String password = dto.getPassword();
        Integer regChannel = dto.getRegChannel();
        String smsCode = dto.getSmsCode();
        AssertUtil.isNotEmpty(mobile, "无效的手机号码!");
        // 根据手机好查询
        EntityWrapper<VipUser> wrapper = new EntityWrapper<>();
        wrapper.eq("phone", mobile);
        VipUser vipUser = super.selectOne(wrapper);
        // 2.判断手机是否已经被注册
        AssertUtil.isNull(vipUser, "手机号码已注册，请直接登录!");
        // 3.判断手机验证码
        // 3.1 获取Redis中的手机验证码
        String key = String.format(RedisConstants.KEY_SMS_CODE, mobile);
        SendVerifyCodeTo sendVerifyCodeTo = (SendVerifyCodeTo) redisTemplate.opsForValue().get(key);
        AssertUtil.isNotNull(sendVerifyCodeTo, "无效的手机验证码，请重新发送!");
        // 3.2.和传入的手机验证码比较
        AssertUtil.isStrEqual(sendVerifyCodeTo.getImageCode(), smsCode, "手机验证码错误");
        // 4.保存Login
        Login login = new Login();
        login.setUsername(mobile);
        login.setPassword(password);
        //前台用户
        login.setType(BaseConstants.login.TYPE_USER);
        login.setTenantId(26L);
        login.setTenantName("源码");
        AjaxResult ajaxResult = loginFeignClient.save(login);
        AssertUtil.isTrue(ajaxResult.isSuccess(), "保存登录失败!");
        AssertUtil.isNotNull(ajaxResult.getResultObj(), "保存登录失败!");
        // 登录id
        Long loginId = Long.valueOf(ajaxResult.getResultObj().toString());
        // 5.保存User
        VipUser user = new VipUser();
        user.setCreateTime(user.getCreateTime());
        user.setPhone(mobile);
        user.setNickName(mobile);
        //默认注册成功的标识
        long bitState = BitStatesUtils.addState(user.getBitState(), BitStatesUtils.OP_ACTIVED);
        //绑定了手机的标识
        bitState = BitStatesUtils.addState(bitState, BitStatesUtils.OP_AUTHED_PHONE);
        user.setBitState(bitState);
        user.setSecLevel(0);
        user.setLoginId(loginId);
        super.insert(user);
        // 6.保存Base
        VipBase vipBase = new VipBase();
        vipBase.setCreateTime(user.getCreateTime());
        vipBase.setSsoId(user.getId());
        // 注册渠道
        vipBase.setRegChannel(regChannel);
        vipBase.setRegTime(vipBase.getCreateTime());
        vipBaseMapper.insert(vipBase);
        // 7.删除手机验证码
        redisTemplate.delete(key);
    }
}
